#include "control.h"
#include "input.h"



/*

Constructor

****************************/

bool Control::bRunning=false;

vector<Node *> Control::nodeTree;               //currently active nodes

Control::Control(){

state=MOVECURSORSTATE;
controlledActor=this;
moveMode=FLYINGCAMERA;                        //as opposed to walking
bDrawOrientation=false;
bPickable=false;
bHidden=true;
name="Control!";

location=Vector3f(0,2,4);
lookPoint=Vector3f(0,2,3);
upPoint=Vector3f(0,1,0);
}

void Control::update(double deltaTime){

    if (!bRunning && state==MOVECAMERASTATE){
        confineMouse();
        processMove(deltaTime);
        }
    if (bRunning){
        updateNodes();
        processMove(deltaTime);
        }
    //TODO: implement further abstraction into loading/saving by making automatic vector loading/saving available!
    //cout << "String Vector: " << typeid(menuType).name() << endl;
    //cout << "Actor* Vector: " << typeid(renderer->actorList).name() << endl;

    }

void Control::updateNodes(){

for (unsigned int i=0;i<nodeTree.size();i++)
  nodeTree[i]->execute();
}

void Control::switchMode(){

bRunning=!bRunning;

if (bRunning)
  start();
else
  stop();
}


void Control::start(){

cout << "starting simulation..." << endl;

    //setup Actors
    for (uint i=0;i<renderer->actorList.size();i++){
      renderer->actorList[i]->initialLocation=renderer->actorList[i]->location;
      renderer->actorList[i]->initialRotation=renderer->actorList[i]->rotation;
      renderer->actorList[i]->start();
    }


    //- setup nodes
    for (uint i=0;i<renderer->nodeList.size();i++)
      renderer->nodeList[i]->start();

    //start node script
    cout << "number of trees: " << nodeTree.size() << endl;

    for (uint i=0;i<nodeTree.size();i++)
      nodeTree[i]->execute();

    //- enable physics
    //todo: disabled for debugging!
   // renderer->bUpdatePhysics=true;
}

void Control::stop(){

cout << "stopping simulation..." << endl;

    //- disable physics
    renderer->bUpdatePhysics=false;

    //- clean up nodes
    for (unsigned int i=0;i<renderer->nodeList.size();i++)
      renderer->nodeList[i]->stop();

    nodeTree.clear();

    for (uint i=0;i<renderer->actorList.size();i++){
      renderer->actorList[i]->location=renderer->actorList[i]->initialLocation;
      renderer->actorList[i]->rotation=renderer->actorList[i]->initialRotation;
      renderer->actorList[i]->stop();
    }

}

void Control::processMove(double deltaTime){

    Matrix4f moveMatrix;
    Vector3f newLocation;

    deltaTime=deltaTime*0.001;


    ///moving
    //ha! that would be too easy
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    //up down should always be along actual x and y axis!
    //x rotation delayed so we simulate head movement!
    glTranslatef(controlledActor->location.x,controlledActor->location.y+input->keyVector.y*renderer->moveSpeed * deltaTime,controlledActor->location.z);
    glRotatef(controlledActor->rotation.y,0,1,0);

    //different movement for mouse-movement or cameraMovement!
    if (controlledActor==this){
        glRotatef(controlledActor->rotation.z,0,0,1);
        glRotatef(controlledActor->rotation.x,1,0,0);
        }
    else{
        glRotatef(controlledActor->rotation.x,1,0,0);
        glRotatef(controlledActor->rotation.z,0,0,1);
        }
    glTranslatef(input->keyVector.x*renderer->moveSpeed *deltaTime,0,input->keyVector.z*renderer->moveSpeed*deltaTime);
    glGetFloatv(GL_MODELVIEW_MATRIX,moveMatrix.data);
    controlledActor->location=moveMatrix.getTranslation();


    glTranslatef(0,0,-1);
    glGetFloatv(GL_MODELVIEW_MATRIX,moveMatrix.data);
    lookPoint=moveMatrix.getTranslation();

    if (controlledActor==this)
      baseMatrix=moveMatrix;

    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    //up Point is absolute!
    glRotatef(controlledActor->rotation.y,0,1,0);
    glRotatef(controlledActor->rotation.z,0,0,1);
    glRotatef(controlledActor->rotation.x,1,0,0);
    glTranslatef(0,1,0);
    glGetFloatv(GL_MODELVIEW_MATRIX,moveMatrix.data);
    upPoint=moveMatrix.getTranslation();

    orientation=location - lookPoint ;

    glPopMatrix();
}

void Control::confineMouse(){

int deltaX;
int deltaY;

deltaX=(int)input->mouseVector.x;
deltaY=(int)input->mouseVector.y;

int centerX=input->windowX+input->screenX/2;
int centerY=input->windowY+input->screenY/2;

//this is windows specific!
input->mouseX=input->screenX/2;
input->mouseY=input->screenY/2;
SetCursorPos(centerX,centerY);
}


void Control::toggleFlyMode(){

if (state==MOVECURSORSTATE)
  {
  state=MOVECAMERASTATE;
  std::cout << "switching to navigation mode! \n";
  glutSetCursor(GLUT_CURSOR_NONE);
  }
else if (state==MOVECAMERASTATE)
  {
  state=MOVECURSORSTATE;
  std::cout << "switching to mouse mode! \n";
  glutSetCursor(GLUT_CURSOR_INHERIT);
  //navButton click!
  }
}



